package com.swc.util;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @author huyupeng
 * @date 2020/9/14 14:35
 */
public class RsaUtil {

    private final static Logger logger = LoggerFactory.getLogger(RsaUtil.class);

    /**
     * 随机生成密钥对
     *
     * @throws NoSuchAlgorithmException
     */
    public static Map<String, Object> genKeyPair() {
        try {
            final Map<String, Object> keyMap = new HashMap<>();
            // KeyPairGenerator类用于生成公钥和私钥对，基于RSA算法生成对象
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
            // 初始化密钥对生成器，密钥大小为96-1024位
            keyPairGen.initialize(1024, new SecureRandom());
            // 生成一个密钥对，保存在keyPair中
            KeyPair keyPair = keyPairGen.generateKeyPair();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
            // 得到私钥字符串 0表示公钥, 1表示私钥
            String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
            // 将公钥和私钥保存到Map
            keyMap.put("publicKey", publicKeyString);
            keyMap.put("privateKey", privateKeyString);
            return keyMap;
        } catch (NoSuchAlgorithmException e) {
            logger.error("生成RSA密钥对异常", e);
        }
        return null;
    }

    /**
     * RSA公钥加密
     *
     * @param message   加密字符串
     * @param publicKey 公钥
     * @return 密文
     * @throws Exception 加密过程中的异常信息
     */
    public static String encrypt(String message, String publicKey) {
        try {
            //base64编码的公钥
            byte[] decoded = Base64.decodeBase64(publicKey);
            RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
            //RSA加密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            String encryptMessage = Base64.encodeBase64String(cipher.doFinal(message.getBytes("UTF-8")));
            return encryptMessage;
        } catch (InvalidKeyException | InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException
                | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) {
            logger.error("使用公钥对数据加密异常", e);
        }
        return null;
    }

    /**
     * RSA私钥解密
     *
     * @param message    加密字符串
     * @param privateKey 私钥
     * @return 铭文
     * @throws Exception 解密过程中的异常信息
     */
    public static String decrypt(String message, String privateKey) {
        try {
            //64位解码加密后的字符串
            byte[] inputByte = Base64.decodeBase64(message.getBytes("UTF-8"));
            //base64编码的私钥
            byte[] decoded = Base64.decodeBase64(privateKey);
            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
            //RSA解密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            String decryptMessage = new String(cipher.doFinal(inputByte));
            return decryptMessage;
        } catch (InvalidKeyException | UnsupportedEncodingException | InvalidKeySpecException | NoSuchAlgorithmException
                | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) {
            logger.error("使用私钥对数据解密异常", e);
        }
        return null;
    }


    public static void main(String[] args) throws Exception {
//        //生成公钥和私钥
//        final Map<String, Object> keyMap = genKeyPair();
//        //需要加密的字符串
//        Map<String, Object> map = new HashMap<>();
//        map.put("userName", "test");
//        map.put("password", "Test@2018");
//        String message = JacksonUtil.mapToJson(map);
//
//        String publicKey = (String) keyMap.get("publicKey");
//        String privateKey = (String) keyMap.get("privateKey");
//
//        logger.info("随机生成的公钥为:" + publicKey);
//        logger.info("随机生成的私钥为:" + privateKey);
//
//        logger.info("明文加密前： " + message);
//
//        String encryptMessage = encrypt(message, publicKey);
//        logger.info("使用公钥加密后的字符串为: " + encryptMessage);
//        String decryptMessage = decrypt(encryptMessage, privateKey);
//        logger.info("私钥还原后的字符串为: " + decryptMessage);

        String publicKey1 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq5cu2nSyGeBnKOn7px3RKNXwgffqBuT1vg5qe7tgpY0T8SZx3SSyfOGuYQ2U5TRAx5HVRiRdghayF1UzqLNYcQ9AqAmCJHUmLnkYBcQnMMnqWI8ZUM5Zc5PS5h56sOBE9jAvX1MiwOG3Q1OijziOjDL4Oez29kXVtogEn8T/riQIDAQAB";
        String privateKey1 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKrly7adLIZ4Gco6funHdEo1fCB9+oG5PW+Dmp7u2CljRPxJnHdJLJ84a5hDZTlNEDHkdVGJF2CFrIXVTOos1hxD0CoCYIkdSYueRgFxCcwyepYjxlQzllzk9LmHnqw4ET2MC9fUyLA4bdDU6KPOI6MMvg57Pb2RdW2iASfxP+uJAgMBAAECgYBLaSFuUIbQQ3jl4tAT6r5m7Jj8YXrD+XChn4oALdbW1IYhaX4QqQp2q9fWlY66LUZDLdOTChJ1tia927SX9Pb5Qic+1X9qRWGsqxxL0Nt1Hxzx849XBTyUif+lJQmXIbVt3b8UceFwP4KitOHkSHRH7xHR3A6iQG9SExmAj9yysQJBAOqZjoF2BhR4SZCmwLoN8UJINxEHnylp62rQeH/E52eMqjKoAGcP90CzFG6QqAeb4WqTDXWS0nmUcphcjNtdmfUCQQC6fKWkSaZSUZJjzLXGwZbpfHJrfuK/ezjTd/pZB1kNfNVlDInP13Tk1K4dzXPD+dCikYp7X1ouKfReP49F9WrFAkAIKHTbLaaCebhdLl9PWQLFwksf7XrsbsGAAmXeU5OUd0DH6C2zZ8u6VT/lpGQjd5k8Iob6SrPFBJODltxTGIstAkEApQMCdrqMpy5ywEg1WGeYJ4XsoN2nuhNIlyYEqZ5s2BhronxTvUtCrfDbGJfhJbn5OMBbrwsSeuK4zmSjXB3qmQJAJTRH7wRYVk6DCtZNVFNy4l3hZ0S4FkzNe70y6PhXoLkoI5Caw+CP0ZvgJM70pAPmKG5Cf16u7j15UwOZ10+T4g==";
        String salt = "QWQ18@QSW134RfC!";
        String encrypt = encrypt(salt, publicKey1);
        System.out.println("加密后：" + encrypt);
        String decrypt = decrypt(encrypt, privateKey1);
        System.out.println("解密后：" + decrypt);
    }


}
